{
  "cells": [
    {
      "cell_type": "code",
      "source": [
        "%pip install --quiet -U \"langchain-community>=0.2.16\" langchain langchain-google-genai"
      ],
      "metadata": {
        "id": "evg3DFIPgsmg"
      },
      "id": "evg3DFIPgsmg",
      "execution_count": 13,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "import getpass\n",
        "import os\n",
        "import json\n",
        "from typing import Dict, Any"
      ],
      "metadata": {
        "id": "bGsy3SSFgtyn"
      },
      "id": "bGsy3SSFgtyn",
      "execution_count": 14,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "if not os.environ.get(\"JINA_API_KEY\"):\n",
        "    os.environ[\"JINA_API_KEY\"] = getpass.getpass(\"Enter your Jina API key: \")\n",
        "\n",
        "if not os.environ.get(\"GOOGLE_API_KEY\"):\n",
        "    os.environ[\"GOOGLE_API_KEY\"] = getpass.getpass(\"Enter your Google/Gemini API key: \")"
      ],
      "metadata": {
        "id": "BRU3XScNgvDy"
      },
      "id": "BRU3XScNgvDy",
      "execution_count": 15,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain_community.tools import JinaSearch\n",
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "from langchain_core.prompts import ChatPromptTemplate\n",
        "from langchain_core.runnables import RunnableConfig, chain\n",
        "from langchain_core.messages import HumanMessage, AIMessage, ToolMessage\n",
        "\n",
        "print(\"🔧 Setting up tools and model...\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1BFBApcigw8J",
        "outputId": "43894a80-d83c-4840-de88-c0758da8a9c9"
      },
      "id": "1BFBApcigw8J",
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🔧 Setting up tools and model...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "search_tool = JinaSearch()\n",
        "print(f\"✅ Jina Search tool initialized: {search_tool.name}\")\n",
        "\n",
        "print(\"\\n🔍 Testing Jina Search directly:\")\n",
        "direct_search_result = search_tool.invoke({\"query\": \"what is langgraph\"})\n",
        "print(f\"Direct search result preview: {direct_search_result[:200]}...\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "mHDVlU2kgyT_",
        "outputId": "2689eacd-e9d6-445d-ae49-da328055e2e5"
      },
      "id": "mHDVlU2kgyT_",
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ Jina Search tool initialized: jina_search\n",
            "\n",
            "🔍 Testing Jina Search directly:\n",
            "Direct search result preview: [{\"title\": \"LangGraph\", \"link\": \"https://www.langchain.com/langgraph\", \"snippet\": \"Build controllable agents with LangGraph, our low-level agent orchestration framework. Deploy and scale with LangGrap...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "gemini_model = ChatGoogleGenerativeAI(\n",
        "    model=\"gemini-2.0-flash\",\n",
        "    temperature=0.1,\n",
        "    convert_system_message_to_human=True\n",
        ")\n",
        "print(\"✅ Gemini model initialized\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4rH8Y9zOgzum",
        "outputId": "1e92fc74-4ffe-406b-dac9-57f6399e5d45"
      },
      "id": "4rH8Y9zOgzum",
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ Gemini model initialized\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "detailed_prompt = ChatPromptTemplate.from_messages([\n",
        "    (\"system\", \"\"\"You are an intelligent assistant with access to web search capabilities.\n",
        "    When users ask questions, you can use the Jina search tool to find current information.\n",
        "\n",
        "    Instructions:\n",
        "    1. If the question requires recent or specific information, use the search tool\n",
        "    2. Provide comprehensive answers based on the search results\n",
        "    3. Always cite your sources when using search results\n",
        "    4. Be helpful and informative in your responses\"\"\"),\n",
        "    (\"human\", \"{user_input}\"),\n",
        "    (\"placeholder\", \"{messages}\"),\n",
        "])"
      ],
      "metadata": {
        "id": "WXDvmp9Bg13Y"
      },
      "id": "WXDvmp9Bg13Y",
      "execution_count": 19,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "gemini_with_tools = gemini_model.bind_tools([search_tool])\n",
        "print(\"✅ Tools bound to Gemini model\")\n",
        "\n",
        "main_chain = detailed_prompt | gemini_with_tools\n",
        "\n",
        "def format_tool_result(tool_call: Dict[str, Any], tool_result: str) -> str:\n",
        "    \"\"\"Format tool results for better readability\"\"\"\n",
        "    return f\"Search Results for '{tool_call['args']['query']}':\\n{tool_result[:800]}...\""
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "c9Wxgaffg4OP",
        "outputId": "530e3280-a76a-4ea9-fd6f-f523d585ae0c"
      },
      "id": "c9Wxgaffg4OP",
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ Tools bound to Gemini model\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "@chain\n",
        "def enhanced_search_chain(user_input: str, config: RunnableConfig):\n",
        "    \"\"\"\n",
        "    Enhanced chain that handles tool calls and provides detailed responses\n",
        "    \"\"\"\n",
        "    print(f\"\\n🤖 Processing query: '{user_input}'\")\n",
        "\n",
        "    input_data = {\"user_input\": user_input}\n",
        "\n",
        "    print(\"📤 Sending to Gemini...\")\n",
        "    ai_response = main_chain.invoke(input_data, config=config)\n",
        "\n",
        "    if ai_response.tool_calls:\n",
        "        print(f\"🛠️  AI requested {len(ai_response.tool_calls)} tool call(s)\")\n",
        "\n",
        "        tool_messages = []\n",
        "        for i, tool_call in enumerate(ai_response.tool_calls):\n",
        "            print(f\"   🔍 Executing search {i+1}: {tool_call['args']['query']}\")\n",
        "\n",
        "            tool_result = search_tool.invoke(tool_call)\n",
        "\n",
        "            tool_msg = ToolMessage(\n",
        "                content=tool_result,\n",
        "                tool_call_id=tool_call['id']\n",
        "            )\n",
        "            tool_messages.append(tool_msg)\n",
        "\n",
        "        print(\"📥 Getting final response with search results...\")\n",
        "        final_input = {\n",
        "            **input_data,\n",
        "            \"messages\": [ai_response] + tool_messages\n",
        "        }\n",
        "        final_response = main_chain.invoke(final_input, config=config)\n",
        "\n",
        "        return final_response\n",
        "    else:\n",
        "        print(\"ℹ️  No tool calls needed\")\n",
        "        return ai_response"
      ],
      "metadata": {
        "id": "qIix6zMYg7U7"
      },
      "id": "qIix6zMYg7U7",
      "execution_count": 21,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def test_search_chain():\n",
        "    \"\"\"Test the search chain with various queries\"\"\"\n",
        "\n",
        "    test_queries = [\n",
        "        \"what is langgraph\",\n",
        "        \"latest developments in AI for 2024\",\n",
        "        \"how does langchain work with different LLMs\"\n",
        "    ]\n",
        "\n",
        "    print(\"\\n\" + \"=\"*60)\n",
        "    print(\"🧪 TESTING ENHANCED SEARCH CHAIN\")\n",
        "    print(\"=\"*60)\n",
        "\n",
        "    for i, query in enumerate(test_queries, 1):\n",
        "        print(f\"\\n📝 Test {i}: {query}\")\n",
        "        print(\"-\" * 50)\n",
        "\n",
        "        try:\n",
        "            response = enhanced_search_chain.invoke(query)\n",
        "            print(f\"✅ Response: {response.content[:300]}...\")\n",
        "\n",
        "            if hasattr(response, 'tool_calls') and response.tool_calls:\n",
        "                print(f\"🛠️  Used {len(response.tool_calls)} tool call(s)\")\n",
        "\n",
        "        except Exception as e:\n",
        "            print(f\"❌ Error: {str(e)}\")\n",
        "\n",
        "        print(\"-\" * 50)"
      ],
      "metadata": {
        "id": "TUzA-M7ohAFv"
      },
      "id": "TUzA-M7ohAFv",
      "execution_count": 22,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "if __name__ == \"__main__\":\n",
        "    print(\"\\n🚀 Starting enhanced LangChain + Gemini + Jina Search demo...\")\n",
        "    test_search_chain()\n",
        "\n",
        "    print(\"\\n\" + \"=\"*60)\n",
        "    print(\"💬 INTERACTIVE MODE - Ask me anything! (type 'quit' to exit)\")\n",
        "    print(\"=\"*60)\n",
        "\n",
        "    while True:\n",
        "        user_query = input(\"\\n🗣️  Your question: \").strip()\n",
        "        if user_query.lower() in ['quit', 'exit', 'bye']:\n",
        "            print(\"👋 Goodbye!\")\n",
        "            break\n",
        "\n",
        "        if user_query:\n",
        "            try:\n",
        "                response = enhanced_search_chain.invoke(user_query)\n",
        "                print(f\"\\n🤖 Response:\\n{response.content}\")\n",
        "            except Exception as e:\n",
        "                print(f\"❌ Error: {str(e)}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jt7j09vYeQ-v",
        "outputId": "ecefe9d6-07f6-43b6-eaaa-b1dc6ed61602"
      },
      "id": "jt7j09vYeQ-v",
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🔧 Setting up tools and model...\n",
            "✅ Jina Search tool initialized: jina_search\n",
            "\n",
            "🔍 Testing Jina Search directly:\n",
            "Direct search result preview: [{\"title\": \"LangGraph\", \"link\": \"https://www.langchain.com/langgraph\", \"snippet\": \"Build controllable agents with LangGraph, our low-level agent orchestration framework. Deploy and scale with LangGrap...\n",
            "✅ Gemini model initialized\n",
            "✅ Tools bound to Gemini model\n",
            "\n",
            "🚀 Starting enhanced LangChain + Gemini + Jina Search demo...\n",
            "\n",
            "============================================================\n",
            "🧪 TESTING ENHANCED SEARCH CHAIN\n",
            "============================================================\n",
            "\n",
            "📝 Test 1: what is langgraph\n",
            "--------------------------------------------------\n",
            "\n",
            "🤖 Processing query: 'what is langgraph'\n",
            "📤 Sending to Gemini...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/langchain_google_genai/chat_models.py:424: UserWarning: Convert_system_message_to_human will be deprecated!\n",
            "  warnings.warn(\"Convert_system_message_to_human will be deprecated!\")\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🛠️  AI requested 1 tool call(s)\n",
            "   🔍 Executing search 1: langgraph\n",
            "📥 Getting final response with search results...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/langchain_google_genai/chat_models.py:424: UserWarning: Convert_system_message_to_human will be deprecated!\n",
            "  warnings.warn(\"Convert_system_message_to_human will be deprecated!\")\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ Response: LangGraph is a framework for building robust and stateful language agents. Here's a breakdown of what it is and its key aspects:\n",
            "\n",
            "**1. Core Functionality:**\n",
            "\n",
            "*   **Agent Orchestration:** LangGraph is designed to help build, manage, and deploy complex AI agent workflows. It provides a way to structur...\n",
            "--------------------------------------------------\n",
            "\n",
            "📝 Test 2: latest developments in AI for 2024\n",
            "--------------------------------------------------\n",
            "\n",
            "🤖 Processing query: 'latest developments in AI for 2024'\n",
            "📤 Sending to Gemini...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/langchain_google_genai/chat_models.py:424: UserWarning: Convert_system_message_to_human will be deprecated!\n",
            "  warnings.warn(\"Convert_system_message_to_human will be deprecated!\")\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🛠️  AI requested 1 tool call(s)\n",
            "   🔍 Executing search 1: latest developments in AI for 2024\n",
            "📥 Getting final response with search results...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/langchain_google_genai/chat_models.py:424: UserWarning: Convert_system_message_to_human will be deprecated!\n",
            "  warnings.warn(\"Convert_system_message_to_human will be deprecated!\")\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "✅ Response: Based on the search results, here are some of the latest developments in AI for 2024:\n",
            "\n",
            "**1. AI Market and Investment:**\n",
            "\n",
            "*   The AI boom drove record valuations and market growth in 2024. Companies like NVIDIA, Broadcom, and Microsoft saw strong revenue growth. NVIDIA's revenue from data center GPUs...\n",
            "--------------------------------------------------\n",
            "\n",
            "📝 Test 3: how does langchain work with different LLMs\n",
            "--------------------------------------------------\n",
            "\n",
            "🤖 Processing query: 'how does langchain work with different LLMs'\n",
            "📤 Sending to Gemini...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/langchain_google_genai/chat_models.py:424: UserWarning: Convert_system_message_to_human will be deprecated!\n",
            "  warnings.warn(\"Convert_system_message_to_human will be deprecated!\")\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "ℹ️  No tool calls needed\n",
            "✅ Response: LangChain is designed to be a versatile framework for working with various Language Models (LLMs). Here's how it achieves this:\n",
            "\n",
            "1.  **LLM Abstraction:** LangChain provides a standard interface for interacting with different LLMs. This abstraction layer allows you to swap out one LLM for another wit...\n",
            "--------------------------------------------------\n",
            "\n",
            "============================================================\n",
            "💬 INTERACTIVE MODE - Ask me anything! (type 'quit' to exit)\n",
            "============================================================\n",
            "\n",
            "🗣️  Your question: quit\n",
            "👋 Goodbye!\n"
          ]
        }
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "poetry-venv-311",
      "language": "python",
      "name": "poetry-venv-311"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.9"
    },
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}